/**
  * @file 		osal.c
  * @brief		轮询式任务调度系统
  *
  * @copyright  Copyright (c) 2020~2030 ShenZhen Dxtc Technology Co., Ltd. 
  * All rights reserved.
  *
  * @version	v3.1
  * @author		FengLi
  * @date 		2021-07-15
  *
  * @note		鼎新同创·智能锁
  * 
  * @par 修改日志:
  * <1> 2021/07/15 v3.1 FengLi 创建初始版本
  *******************************************************************/
#include "osal.h"
#include "osport.h"
#include "device.h"
#include "component.h"


/** @brief   ASSERT（断言） */
#define OSAL_ASSERT( x ) if ((x) == 0) { __OSAL_LOG("[osal.c:%05d] ASSERT\r\n", __LINE__); Device_EnterCritical(); for( ;; ); }

/** @brief   任务表结构 */
typedef struct
{
	uint32_t (*pTaskFun)(uint32_t); ///< 任务函数
    SuperQueueHandle_t queue;       ///< 队列句柄（邮箱功能用到）
    
    uint16_t comp_id;               ///< 当前任务对应的组件名称（组件ID）
    uint8_t  alias;                 ///< 当前任务对应的组件别名（昵称）
    TaskStatus_enum_t status;       ///< 任务状态

    uint32_t nv_addr;  ///< 当前任务（组件）分配的NV区域的首地址
    uint32_t nv_size;  ///< 当前任务（组件）分配的NV区域的大小
}Task_stu_t;

/** @brief   OSAL状态 */
static enum
{
    OSAL_STA_INIT = UINT32_FLAG,
    OSAL_STA_SLEEP,       ///< 休眠    （正在执行TASK休眠事件：EVENT_SYS_SLEEP、或者已休眠）
    OSAL_STA_START_TASK,  ///< 启动TASK（正在执行TASK启动事件：EVENT_SYS_START）
    OSAL_STA_START_APP,   ///< 启动APP （正在执行APP层入口函数）
    OSAL_STA_ACTIVE,      ///< 活跃    （系统已启动）
}osalStatus = OSAL_STA_INIT;

/** @brief   软定时器类型 
 * 
 * 定时器分为两种：定时创建事件和定时执行函数
 * 定时函数：timer_cb非空
 *   A、evt_index：表示应用ID，即APP-ID/APP-INDEX（非应用层创建的定时器，值为FF）
 *   B、events：表示软定时器的参数（创建定时器时传入）（该参数目前仅在自动休眠定时器里面用到了，暂未开放给外部使用）
 * 
 * 定时事件：timer_cb为空
 *   A、evt_index:事件索引
 *   B、events:事件值
 */
typedef struct __timer
{
    void (*timer_cb)(TimerHandle_stu_t); ///< 定时器回调函数

	uint32_t events;                 ///< 事件值
	uint16_t evt_index;              ///< 事件索引

	FlagStatus repeat;               ///< 重复定时标记
    TimerStatus_enum_t status;       ///< 定时器状态

	uint32_t delay;     ///< 定时的时间
	uint32_t timestamp; ///< 定时器启动的时刻
	
	struct __timer *next;  ///< 双向链表指针，指向下一个节点
	struct __timer *prev;  ///< 双向链表指针，指向前一个节点
}TimerType_stu_t;


uint8_t    g_TaskQty;                           ///< 已注册的任务数量
uint16_t   g_ActiveTaskIndex = TASK_NO_TASK;    ///< 当前正在运行的任务ID
uint16_t   g_ActiveAppIndex = APP_NO_APP;       ///< 当前正在运行的APP-ID
FlagStatus g_SystemResetFlag = RESET;           ///< 系统RESET标志

__NVRAM static uint32_t wake_id = TASK_NO_TASK; ///< 唤醒ID（TASK-ID）（组件ID）（默认值为调度器ID，表示上电唤醒）
__NVRAM static uint32_t wake_param = 0;         ///< 唤醒参数（唤醒回调接口的返回值）

static TimerType_stu_t *pTimersListHead = NULL; ///< 软定时器头指针
static TimerType_stu_t *pActiveTimer = NULL;    ///< 指向当前正在执行回调的定时器
static uint32_t eventListMaxRange = 0;          ///< 轮询事件表时，调度器轮询的最大范围
static volatile uint32_t xTickCount = 0;        ///< 系统滴答计数器

static Task_stu_t *pTasksList = NULL;           ///< 任务表
static uint32_t *pSleepEventsList = NULL;       ///< 任务休眠事件表（休眠状态下产生的事件暂存在这个表）
static uint32_t *pEventsList = NULL;            ///< 事件表：任务表对应3个事件表（高、中、低优先级事件）

static uint32_t app_nv_addr = 0;                ///< 应用层的NV区域首地址
static uint32_t app_nv_size = 0;                ///< 应用层的NV区域大小

static FlagStatus sync_flag = RESET;            ///< 标记当前是否给主机发送过SYNC命令
static FlagStatus publish_flag = RESET;         ///< 标记当前是否给主机发送过Publish命令

static uint32_t wakeup_interval = KOS_PARAM_WAKE_INTERVAL;      //唤醒间隔值

#if defined(KOS_PARAM_ROLE_SLAVE)
static SuperQueueHandle_t publish_queue = NULL; ///< publish缓存队列
#endif

#if KOS_PARAM_SLEEP_FUNC
static TimerHandle_stu_t auto_sleep_timer_handle;   ///< 自动休眠定时器的句柄
#endif

__attribute__((weak)) void OSAL_LoopHook(void);
static inline void OSAL_EventSet(uint32_t index, uint32_t events);

extern void OSAL_AppMain(uint32_t wake_id, uint32_t wake_param);
extern void OSAL_MessageAdd(uint16_t comp_id, uint8_t *data, uint16_t len);

/**
  * @brief  发送SYNC命令给主机（给主机同步TASK-INFO、NV、Rm、Rs） -- 从机端
  * @details 详细说明:TASK-INFO内容：  task_qty   opt   COMP-ID  ALIAS  STA  NV-SIZE  NV-DATA  COMP-ID  ALIAS  STA   NV-SIZE  NV-DATA  ……
  *         
  * @param[in]  task_index：任务索引（0XFF：表示给主机同步所有的TASK、Rm、Rs）
  *         
  * @return NULL
  */
__attribute__((weak)) void OSAL_SendSync(uint8_t task_index, uint32_t rm, uint32_t rs)
{
    uint16_t buffer_len = 0, cnt = 0;
    uint8_t *pTask_info = NULL;

#ifdef KOS_PARAM_OSPORT_CRYPTO
    buffer_len = (task_index == 0xFF) ? 8 : 0;
#endif
    for (int i=0; i<g_TaskQty; i++)
    {
        if (task_index == i || task_index == 0xFF)
        {
            uint8_t nvsize = (pTasksList[i].nv_size > OSPORT_vTASK_NV_SIZE) ? (OSPORT_vTASK_NV_SIZE) : (pTasksList[i].nv_size);
            buffer_len += 4 + nvsize;
        }
    }

#ifdef KOS_PARAM_OSPORT_CRYPTO
    if(buffer_len == 0)
    {
        return ;
    }
#endif

    pTask_info = (uint8_t *)OSAL_Malloc(buffer_len);
    OSAL_ASSERT(pTask_info != NULL);

    for (int i=0; i<g_TaskQty; i++)
    {
        if (task_index == i || task_index == 0xFF)
        {
            uint8_t nvsize = (pTasksList[i].nv_size > OSPORT_vTASK_NV_SIZE) ? (OSPORT_vTASK_NV_SIZE) : (pTasksList[i].nv_size);
            pTask_info[cnt++] = pTasksList[i].comp_id;
            pTask_info[cnt++] = pTasksList[i].alias;
            pTask_info[cnt++] = pTasksList[i].status;
            pTask_info[cnt++] = nvsize;
            Device_Read(vEEPROM_0, &pTask_info[cnt], nvsize, pTasksList[i].nv_addr);
            cnt += nvsize;
        }
    }

    uint8_t qty = 1, opt = 1;
    if (task_index == 0xFF)
    {
        qty = g_TaskQty;
        opt = 0;
    #ifdef KOS_PARAM_OSPORT_CRYPTO
        memcpy(&pTask_info[cnt], &rm, 4);
        memcpy(&pTask_info[cnt+4], &rs, 4);
    #endif
    }
    OSAL_OsPortSend((VirtualHardware_enum_t)0, OSPORT_CMD_SYNC, qty, opt, pTask_info, buffer_len);
    OSAL_Free( pTask_info );
}

/**
  * @brief  OSPORT状态改变---从机端
  *         
  * @param[in]  port：端口号
  * @param[in]  status：状态--离线、上线
  */
__attribute__((weak)) void OSAL_OsportStateChange(VirtualHardware_enum_t port, FlagStatus status)
{
#if defined(KOS_PARAM_ROLE_SLAVE)
    if (status == SET)
    {
        //< 端口上线发起握手
        uint32_t number = 0;
        sync_flag = RESET;
        OSAL_Crypto(CALC_RANDOM_NUMBER, NULL, 4, &number, NULL);
        OSAL_OsPortSend((VirtualHardware_enum_t)0, OSPORT_CMD_HELLO, wake_id, wake_param, &number, sizeof(number));
    }
    else
    {
        //< 端口离线重新连接
        Device_Write(port, NULL, 0, BLE_CTRL_CONNECT);
    }
#endif
}

/**
  * @brief  启动应用层 -- 从机端
  * @details 详细说明:无
  *         
  * @param[in]  id: 任务ID
  * @param[in]  param: 命令说明参数，详细请参考多核通信协议文档
  *         
  * @return NULL
  */
__attribute__((weak)) void OSAL_AppStart(uint32_t id, uint32_t param)
{
    __OSAL_LOG("[osal.c] App start, Free heap size:%d\r\n", OSAL_GetFreeHeapSize());

#if defined(KOS_PARAM_ROLE_SLAVE)
    sync_flag = RESET;
    OSAL_AppMain(id, param);
#else
    /**
     * @brief 1、被主机唤醒：不用发起握手
     *        2、上电启动：给主机发HELLO命令n次，间隔200ms循环发，直到主机转发了HELLO，然后从机再发出SYNC后才会退出
     *        3、本地唤醒：给主机发HELLO命令1次
     */
    if (id == TASK_ID_IDLE && param != 1)
    {
        //< 被主机唤醒
    }
    else
    {
        //< 本地唤醒
        uint32_t delay = 0, number = 0;
        #if defined(KOS_PARAM_OSPORT_CRYPTO)
        OSAL_Crypto(CALC_RANDOM_NUMBER, NULL, 4, &number, NULL);
        #endif
        do
        {
            if (delay == 0)
            {
                OSAL_OsPortSend((VirtualHardware_enum_t)0, OSPORT_CMD_HELLO, (uint8_t)id, (uint8_t)param, &number, sizeof(number));
            }
            else
            {
                OSAL_OsPortProcess();
                Device_DelayUs(999);
                Device_FeedDog();
            }
            delay = (delay < 200) ? (delay + 1) : 0;
        }while ((sync_flag == RESET) && (id == 0xFF));
    }
    #if KOS_PARAM_SLEEP_FUNC
    OSAL_UpdateSleepTime(10000, 1);
    #endif
#endif
}

/**
  * @brief  APP链表表初始化——此处为弱函数
  * @details  详细说明：申请APP控制块内存并清空，初始消息列表
  * 
  * @return   NULL         
  */
__attribute__((weak)) void OSAL_ApplicationInit(void)
{

}

/**
  * @brief  获取app的状态——此处为弱函数
  * @details  详细说明：无
  *         
  * @param[in]  app_id：需要获取的APP-ID
  * 
  * @return   【-1】:错误（app不存在）
  */
__attribute__((weak)) int OSAL_AppStateGet(uint32_t app_id)
{
    return -1;
}

/**
  * @brief  OSAL消息服务——此处为弱函数
  * @details 详细说明：将组件层发布的消息，推给APP层
  *         
  * @return NULL 
  */
__attribute__((weak)) void OSAL_MessageBroker(void)
{

}

//! ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
  * @brief  OSAL-LOOP 钩子函数
  * @details 详细说明：无
  *         
  * @return NULL
  */
__attribute__((weak)) void OSAL_LoopHook(void)
{
    ;
}

/**
  * @brief  OSAL-START 钩子函数
  * @details 详细说明：无
  *         
  * @return NULL
  */
__attribute__((weak)) void OSAL_StartHook(void)
{
    ;
}

/**
  * @brief  OSAL-SYSTICK 钩子函数
  * @details 详细说明：无
  *         
  * @return ERROR：错误
  */
__attribute__((weak)) ErrorStatus OSAL_SystickHook(uint32_t *tick)
{
    return ERROR;
}

/**
  * @brief  获取当前tick值
  * @details 详细说明：无
  *         
  * @return 返回tick值
  */
inline static uint32_t OSAL_GetTick(void)
{
    uint32_t xTick = 0;

    if (OSAL_SystickHook(&xTick) == SUCCESS)
    {
        return xTick;
    }
    else
    {
        return xTickCount;
    }
}

/**
  * @brief  获取系统滴答计数值
  * @details 详细说明：无
  *         
  * @return 当前计数值
  */
uint32_t OSAL_GetTickCount(void)
{
    const uint32_t xTicks = OSAL_GetTick();
    return xTicks;
}

/**
  * @brief  补偿tick值（当休眠后SysTick无法运行时，再次唤醒要补偿tick值）
  */
void OSAL_StepTickCount(uint32_t tick)
{
	xTickCount += tick;
}

/**
  * @brief  根据TASK索引，找到对应的组件ID
  * @details 详细说明：无
  *    
  * @param[in]  task_index：任务ID
  *         
  * @return 返回组件ID
  */
uint16_t OSAL_TaskIndex2CompId(uint16_t task_index)
{
    if (task_index < g_TaskQty)
    {
        return pTasksList[task_index].comp_id;
    }
    return 0XFF;
}

/**
  * @brief  根据组件ID，找到对应的TASK索引
  * @details 详细说明：无
  *    
  * @param[in]  task_index：组件ID
  *         
  * @return 返回TASK-INDEX
  */
uint16_t OSAL_CompId2TaskIndex(uint16_t comp_id)
{
    for (int i=0; i<g_TaskQty; i++)
    {
        if (pTasksList[i].comp_id == comp_id)
        {
            return i;
        }
    }
    return 0XFF;
}
//! /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
  * @brief  初始化TimerList
  * @details 详细说明：创建定时器链表头
  *    
  *         
  * @return NULL
  */
static void OSAL_TimerListInit(void)
{
	pTimersListHead = (TimerType_stu_t *)OSAL_Malloc(sizeof(TimerType_stu_t));

    OSAL_ASSERT(pTimersListHead);

    memset(pTimersListHead, 0, sizeof(TimerType_stu_t));
    pTimersListHead->next = NULL;
    pTimersListHead->prev = NULL;
}

/**
  * @brief  添加一个软定时器
  * @details 详细说明：无
  *    
  * @param[in]  index：事件索引
  * @param[in]  event：事件值
  * @param[in]  xTicks：延时值（系统滴答节拍数）
  * @param[in]  timer_cb：定时器回调函数（用作定时事件时，该参数为空）
  * @param[in]  repeat：重复定时标志（SET：重复定时，RESET：单次定时）
  *         
  * @return 返回定时器控制块（TCB）地址
  */
static TimerHandle_stu_t OSAL_TimerAdd(uint16_t index, uint32_t events, void(*timer_cb)(TimerHandle_stu_t), uint32_t xTicks, FlagStatus repeat)
{
	TimerType_stu_t *pTimer = pTimersListHead;
	const uint32_t xConstTickCount = OSAL_GetTick();
	
	for (; pTimer->next != NULL; pTimer = pTimer->next)
	{
		if ((pTimer->next->events == events && pTimer->next->evt_index == index && timer_cb == NULL) //< 定时器列表已存在这个定时事件
         || (timer_cb != NULL && timer_cb == pTimer->next->timer_cb)) //< 定时器列表已存在这个定时函数
		{
            pTimer->next->timestamp = xConstTickCount;
            pTimer->next->delay = xTicks;
		    pTimer->next->repeat = repeat;
		    pTimer->next->events = events;
			return (void*)(pTimer->next);
		}
	}
	
	pTimer->next = (TimerType_stu_t *)OSAL_Malloc(sizeof(TimerType_stu_t));
	if (pTimer->next != NULL)
	{
		pTimer->next->prev = pTimer;
		pTimer->next->next = NULL;
		
		pTimer->next->events = events;
		pTimer->next->evt_index = index;
		pTimer->next->delay = xTicks;
		pTimer->next->timer_cb = timer_cb;
		pTimer->next->timestamp = xConstTickCount;
		pTimer->next->repeat = repeat;
        pTimer->next->status = TIM_RUN_WAKE_SLEEP;
		
        if (timer_cb == NULL)//< 定时事件
        {
            /* 添加了高优先级周期事件，调度器只轮询高优先级和中优先级事件表（前2个事件表），不处理低优先级事件 */
		    eventListMaxRange = (index < g_TaskQty) ? (g_TaskQty * 2) : eventListMaxRange;
        }
	}
	return (void*)(pTimer->next);
}

/**
  * @brief  更新 Timer list
  * @details 详细说明：无
  *    
  *         
  * @return NULL
  */
static void OSAL_TimerListUpdate(void)
{
	TimerType_stu_t *pTimer = pTimersListHead;
	FlagStatus highProFlag = RESET;

	pTimer = pTimer->next;
	for (; pTimer != NULL; pTimer = pTimer->next)
	{
        if (osalStatus != OSAL_STA_ACTIVE)
        {
            break;
        }

        if (pTimer->status == TIM_STOP)
        {
            continue;
        }

        if (pTimer->timer_cb == 0)//< 定时事件
        {
		    highProFlag = (pTimer->evt_index < g_TaskQty) ? SET : highProFlag;
        }
		
	    uint32_t xConstTickCount = OSAL_GetTick();
		if (OSAL_PastTime(xConstTickCount, pTimer->timestamp) >= pTimer->delay)
		{
            if (pTimer->timer_cb == 0)
            {
			    OSAL_EventSet(pTimer->evt_index, pTimer->events);//< 定时事件
            }
            else if (OSAL_AppStateGet(pTimer->evt_index) != 0)
            {
                pActiveTimer = pTimer;
                g_ActiveAppIndex = pTimer->evt_index;
                pTimer->timer_cb(pTimer);    //< 定时function
                g_ActiveAppIndex = APP_NO_APP;
                pActiveTimer = NULL;
            }

			if (pTimer->repeat == RESET)
			{
				pTimer = pTimer->prev;
				OSAL_TimerDelete(pTimer->next);
			}
			else
			{
				pTimer->timestamp = xConstTickCount;
			}
		}
	}
	
	/* 没有一个高优先级周期事件，调度器轮询所有事件（3个事件表全部轮询） */
	eventListMaxRange = (highProFlag == RESET) ? (g_TaskQty * 3) : eventListMaxRange;
}

#if KOS_PARAM_SLEEP_FUNC
/**
  * @brief  计算Timer list里面每个定时器的剩余定时时间,返回最小的那个值
  * @details 详细说明：无
  *    
  *         
  * @return NULL
  */
static uint32_t OSAL_TimerGetMin(void)
{
	TimerType_stu_t *pTimer = pTimersListHead;
	const uint32_t xConstTickCount = OSAL_GetTick();
    uint32_t value = UINT32_MAX;

	pTimer = pTimer->next;
	for (; pTimer != NULL; pTimer = pTimer->next)
	{
        if (pTimer->timer_cb == 0)
        {
            continue;//< 定时事件
        }

        if (OSAL_AppStateGet(pTimer->evt_index) == 0)
        {
            continue;//< APP禁能了
        }

        if (pTimer->status != TIM_RUN_WAKE_SLEEP)
        {
            continue;
        }

        uint32_t past_time = OSAL_PastTime(xConstTickCount, pTimer->timestamp);
        uint32_t time = (past_time < pTimer->delay) ? (pTimer->delay - past_time) : 0;

        value = (value < time) ? value : time;
        __OSAL_LOG("timer_cb:%p, %ld\r\n", pTimer->timer_cb, time);
	}
	return value;
}
#endif

/**
  * @brief  设置定时器状态
  * @details 详细说明:无
  *         
  * @param[in]  handle：定时器句柄
  * @param[in]  status：状态
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误）
  */
ErrorStatus OSAL_TimerSet(TimerHandle_stu_t handle, TimerStatus_enum_t status)
{
    TimerType_stu_t *pTimer = (TimerType_stu_t *)handle;

	OSAL_ASSERT((pTimer != NULL) && (pTimer != pTimersListHead));
    pTimer->status = status;
    return SUCCESS;
}

/**
  * @brief  获取一个定时器的剩余时间
  * @details 详细说明:无
  *         
  * @param[in]  handle：定时器句柄
  *         
  * @return 返回该定时器的剩余时间
  */
uint32_t OSAL_TimerGetRemaining(TimerHandle_stu_t handle)
{
    TimerType_stu_t *pTimer = (TimerType_stu_t *)handle;
    if (handle == NULL)
    {
        return UINT32_MAX;
    }
    uint32_t xConstTickCount = OSAL_GetTick();
    uint32_t past_time = OSAL_PastTime(xConstTickCount, pTimer->timestamp);
    return (pTimer->delay > past_time) ? (pTimer->delay - past_time) : 0;
}

/**
  * @brief  删除一个定时器
  * @details 详细说明:无
  *         
  * @param[in]  handle：要删除的软定时控制块地址
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_TimerDelete(TimerHandle_stu_t handle)
{
    TimerType_stu_t *pTimer = (TimerType_stu_t *)handle;

	OSAL_ASSERT((pTimer != NULL) && (pTimer != pTimersListHead));

    if (pTimer == pActiveTimer)
    {
        pTimer->repeat = RESET;
        return SUCCESS;
    }

    /* Check if it's a valid timer */
    TimerType_stu_t *pTimer1 = pTimersListHead;
    while (pTimer1)
	{
		if (pTimer1 == pTimer)
        {
            break;
        }
        pTimer1 = pTimer1->next;
	}

    if (pTimer1 == NULL)
    {
        __OSAL_LOG("[osal.c] unknown timer\r\n");
        return ERROR;
    }

	pTimer->prev->next = pTimer->next;
	if (pTimer->next != NULL)
	{
		pTimer->next->prev = pTimer->prev;
	}
	OSAL_Free(pTimer);
	return SUCCESS;
}

/**
  * @brief  创建定时执行的函数
  * @details 详细说明:无
  *         
  * @param[in]  param：回调参数
  * @param[in]  timer_cb：定时器回调函数（用作定时事件时，该参数为空）
  * @param[in]  xTicks：延时值（系统滴答节拍数）
  * @param[in]  repeat：重复定时标志（SET：重复定时，RESET：单次定时）
  *         
  * @return 返回TCB指针（定时器句柄）
  */
TimerHandle_stu_t OSAL_TimerCreate(void(*timer_cb)(TimerHandle_stu_t), uint32_t xTicks, FlagStatus repeat)
{
    OSAL_ASSERT((timer_cb != NULL) && (xTicks > 0));
    return OSAL_TimerAdd(g_ActiveAppIndex, 0, timer_cb, xTicks, repeat);
}
//! /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
  * @brief  设置一个事件
  * @details 详细说明：无
  *    
  * @param[in]  index：事件索引
  * @param[in]  event：事件值
  *         
  * @return NULL
  */
static inline void OSAL_EventSet(uint32_t index, uint32_t events)
{
    if (osalStatus == OSAL_STA_ACTIVE)
    {
    	Device_EnterCritical();
	    pEventsList[index] |= events;
    	Device_ExitCritical();
    }
    else
    {
    	Device_EnterCritical();
        pSleepEventsList[index] |= events;
    	Device_ExitCritical();
    }
}

/**
  * @brief  直接创建一个事件（中断版本）
  * @details 详细说明:无
  *         
  * @param[in]  task_id：任务ID
  * @param[in]  event：事件
  * @param[in]  priority：事件优先级
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_EventCreateFromISR(uint16_t comp_id)
{
	uint16_t task_index = OSAL_CompId2TaskIndex(comp_id);
	
    OSAL_ASSERT(task_index < g_TaskQty);
    OSAL_EventSet(task_index, EVENT_SYS_ISR);
    return SUCCESS;
}

/**
  * @brief  通用的事件创建API
  * @details 详细说明:无
  *         
  * @param[in]  task_id：任务ID
  * @param[in]  event：事件
  * @param[in]  xTicks：延时的节拍数
  * @param[in]  repeat：重复标志（SET:重复创建该事件（重复创建事件，xTicks不能为0）；RESET:单次创建该事件）
  * @param[in]  priority：事件优先级
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_EventGenerictCreate(uint16_t comp_id, uint32_t events, uint32_t xTicks, FlagStatus repeat, EventPriority_enum_t priority)
{
	uint16_t index;
	uint16_t task_index = OSAL_CompId2TaskIndex(comp_id);

    OSAL_ASSERT(task_index < g_TaskQty);
    OSAL_ASSERT(!(xTicks == 0 && repeat == SET));
	
	index = task_index + ((int)priority * g_TaskQty);
	if (xTicks > 0)
	{
		return ( (OSAL_TimerAdd(index, events, NULL, xTicks, repeat) != NULL) ? SUCCESS : ERROR );
	}
	else
	{     
		OSAL_EventSet(index, events);	
		return SUCCESS;
	}
}

/**
  * @brief  删除一个事件
  * @details 详细说明:无
  *         
  * @param[in]  task_id：任务ID
  * @param[in]  event：事件值
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_EventDelete(uint16_t comp_id, uint32_t events)
{
    TimerType_stu_t *pTimer = pTimersListHead;
    uint16_t task_index;

    task_index = OSAL_CompId2TaskIndex(comp_id);
    OSAL_ASSERT(task_index < g_TaskQty);

    Device_EnterCritical();
    pEventsList[task_index] &= ~events;
    pEventsList[task_index + g_TaskQty] &= ~events;
    pEventsList[task_index + g_TaskQty * 2] &= ~events;
    Device_ExitCritical();

    for (; pTimer->next != NULL; pTimer = pTimer->next)
    {
        if (pTimer->next->events == events && (pTimer->next->evt_index % g_TaskQty) == task_index && pTimer->next->timer_cb == NULL)
        {
            OSAL_TimerDelete(pTimer->next);
            break;
        }
    }
    return SUCCESS;
}
//! /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
  * @brief  Task列表头部
  * @details 详细说明：只是提供一个函数地址，无意义
  *         
  * @return 【0】：NULL
  */
static uint32_t OSAL_TaskTable_Start(uint32_t wakesource)
{
    return 0;
}

/** @brief   挂载TASK任务入口（首端）函数 */
COMPONENT_TASK_START_EXPORT(OSAL_TaskTable_Start);

/**
  * @brief  Task列表尾部
  * @details 详细说明：只是提供一个函数地址，无意义
  *         
  * @return 【0】：NULL
  */
static uint32_t OSAL_TaskTable_End(uint32_t wakesource)
{
    return 0;
}

/** @brief   挂载TASK任务出口（末端）函数 */
COMPONENT_TASK_END_EXPORT(OSAL_TaskTable_End);

/**
  * @brief  任务表初始化
  * @details 详细说明：初始化系统用到的一些数据表
  *         
  * @return  NULL
  */
static void OSAL_TaskListInit(void)
{
    const ComPonent_TaskInfo_stu_t *fn_ptr = &__ComPonent_Task_OSAL_TaskTable_Start;
    
    g_TaskQty = &__ComPonent_Task_OSAL_TaskTable_End - fn_ptr - 1;
    __OSAL_LOG("[osal.c] task qty:%d\r\n", g_TaskQty);
    
    pTasksList = (Task_stu_t*)OSAL_Malloc(sizeof(Task_stu_t) * g_TaskQty);
    pEventsList = (uint32_t*)OSAL_Malloc(sizeof(uint32_t) * g_TaskQty * 3);
    pSleepEventsList = (uint32_t*)OSAL_Malloc(sizeof(uint32_t) * g_TaskQty * 3);
    eventListMaxRange = g_TaskQty * 3;

    /* check */
    OSAL_ASSERT((pTasksList != NULL) && (pEventsList != NULL) && (pSleepEventsList != NULL));

    /* clear memory */
    memset(pTasksList, 0, sizeof(Task_stu_t) * g_TaskQty);
    memset(pEventsList, 0, sizeof(uint32_t) * g_TaskQty * 3);
    memset(pSleepEventsList, 0, sizeof(uint32_t) * g_TaskQty * 3);

    /* create task list */
    for (int i=0; i<g_TaskQty; i++)
    {
        fn_ptr++;
        pTasksList[i].status = TASK_STA_NORMAL;
        pTasksList[i].comp_id  = fn_ptr->ComPonent_Task_ID;
        pTasksList[i].pTaskFun = fn_ptr->ComPonent_Task_FN;
        pTasksList[i].nv_size  = fn_ptr->nv_size;
        pTasksList[i].alias = 0;
        pTasksList[i].queue = OSAL_QueueCreate(KOS_PARAM_MBOX_LEN);
        OSAL_ASSERT(pTasksList[i].queue != NULL);
    }

    /* 根据组件ID进行排序、组件ID越小越靠前、优先级越高 */
    for (int i=0; i<g_TaskQty-1; i++)
    {
        for (int j=i+1; j<g_TaskQty; j++)
        {
            if (pTasksList[i].comp_id > pTasksList[j].comp_id)
            {
                Task_stu_t temp = pTasksList[i];
                pTasksList[i] = pTasksList[j];
                pTasksList[j] = temp;
            }
        }
    }

    uint32_t addr = 0;
    uint32_t nv_mem_size = Device_GetDeviceCtrlBlock(vEEPROM)->devParam;
    __OSAL_LOG(C_LIGHT_BLUE "NV_MEM_SIZE:%ld\r\n\r\n", nv_mem_size);

#ifdef KOS_PARAM_OSPORT_CRYPTO
    addr = 512; //< 前512字节预留给KOS内部使用
#endif
    /* 给各个组件分配NV空间 */
    for (int i=0; i<g_TaskQty; i++)
    {
        if ((addr + pTasksList[i].nv_size) <= nv_mem_size)
        {
            pTasksList[i].nv_addr = addr;
            addr += pTasksList[i].nv_size;
            __OSAL_LOG("TASK_INDEX:%-3d   COMP_ID:%-3d   NV_ADDR:%-5ld   NV_SIZE:%-5ld\r\n", i, pTasksList[i].comp_id, pTasksList[i].nv_addr, pTasksList[i].nv_size);
        }
        else
        {
            __OSAL_LOG("TASK_INDEX:%-3d   COMP_ID:%-3d   NV_ADDR:%-5ld   NV_SIZE:%-5ld    ", i, pTasksList[i].comp_id, pTasksList[i].nv_addr, pTasksList[i].nv_size);
            __OSAL_LOG(C_COLOR C_LIGHT_RED "NV Allocation error\r\n" C_NONE C_LIGHT_BLUE);
            pTasksList[i].nv_size = 0;
        }
    }

    /* 给应用层分配NV空间 */
    app_nv_addr = addr;
    app_nv_size = nv_mem_size - addr;
    __OSAL_LOG("\r\nAPPLICATION   NV_ADDR:%-5ld   NV_SIZE:%ld\r\n\r\n\r\n", app_nv_addr, app_nv_size);
    __OSAL_LOG(C_NONE);
}

/**
  * @brief  OSAL启动
  * @details 详细说明：给所有任务创建启动事件，将OSAL状态标记为：启动态
  *         
  * @return  NULL
  */
static void OSAL_Start(void)
{
	Device_EnterCritical();
    for (int i=0; i<g_TaskQty; i++)
    {
        pEventsList[i] = EVENT_SYS_START;
    }
	Device_ExitCritical();
}

/**
  * @brief  复制OSAL休眠时产生的事件
  * @details 详细说明：休眠时：事件都会暂存在pSleepEventsList里面，唤醒后再复制到正常事件表里面
  *         
  * @return  NULL
  */
static void OSAL_CopySleepEvent(void)
{
    for (int index = 0; index < g_TaskQty * 3; index++)
    {
        if (pSleepEventsList[index] != 0)
        {
            Device_EnterCritical();
            pEventsList[index] |= pSleepEventsList[index];
            pSleepEventsList[index] = 0;
            Device_ExitCritical();
        }
    }
}

#if KOS_PARAM_SLEEP_FUNC
/**
  * @brief  OSAL休眠
  * @details 详细说明：给所有任务创建休眠事件；将OSAL状态标记为：休眠态
  *         
  * @return  如果此时事件表里面又有ISR事件了：返回失败（可能某个中断置起了ISR事件）
  */
static ErrorStatus OSAL_Sleep(void)
{
	Device_EnterCritical();
	for (uint16_t index = 0; index < g_TaskQty; index++)
	{
		if (pEventsList[index] & EVENT_SYS_ISR)
        {
            Device_ExitCritical();
            return ERROR;
        }
	}
    osalStatus = OSAL_STA_SLEEP;
    memset(pEventsList, 0, sizeof(uint32_t) * g_TaskQty * 3);
    Device_ClearInterrupt();
	for (uint16_t index = 0; index < g_TaskQty; index++)
	{
		pEventsList[index] = EVENT_SYS_SLEEP;
	}
	Device_ExitCritical();
    __OSAL_LOG("[osal.c] set sleep event\r\n");
    return SUCCESS;
}

/**
  * @brief  检查TASK的状态
  * @details 详细说明:无
  *         
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_TaskStatusCheckLocal(void)
{
    for (int i = 0; i < g_TaskQty; i++)
    {
        if (pTasksList[i].status == TASK_STA_ACTIVE)
        {
            __OSAL_LOG("[osal.c] sleep failed, task is active, comp_id: %d\r\n", pTasksList[i].comp_id);
            return ERROR;
        }
    }
    return SUCCESS;
}

/**
  * @brief  WAKEUP表 起始
  * @details 详细说明:只提供一个函数地址，无意义。
  *         
  *         
  * @return 【0】：NULL
  */
static int32_t OSAL_WakeupHandlerStart(uint32_t dev)
{
    return 0;
}

/** @brief   挂载唤醒回调入口（首端）函数 */
COMPONENT_WAKEUP_START_EXPORT(OSAL_WakeupHandlerStart);

/**
  * @brief  WAKEUP表 结束
  * @details 详细说明:只提供一个函数地址，无意义。
  *         
  *         
  * @return 【0】：NULL
  */
static int32_t OSAL_WakeupHandlerEnd(uint32_t dev)
{
    return 0;
}

/** @brief   挂载唤醒回调出口（末端）函数 */
COMPONENT_WAKEUP_END_EXPORT(OSAL_WakeupHandlerEnd);

/**
  * @brief  处理唤醒逻辑
  * @details 详细说明:硬件触发了中断，尝试唤醒系统时，确认是否允许唤醒
  *                   例如：距离传感器INT触发后，需要读到具体距离数据才能唤醒
  *         
  * @param[in]  dev：中断源
  *         
  * @return 【SUCCEE】：允许唤醒   【ERROR】：不允许唤醒
  */
ErrorStatus OSAL_WakeupHandler(uint32_t dev)
{
    int32_t param = -1;
    const ComPonent_Wakeup_stu_t *pWake = &__ComPonent_Wakeup_OSAL_WakeupHandlerStart0;
#if defined(SLEEP_CHECK_OCEP_STATUS)
    static uint16_t wakeTimes = 0;

    wakeTimes++;
#endif
    if (OSAL_OsPortCheckWakeDevice((VirtualHardware_enum_t)dev) != ERROR)
    {
        wake_id = TASK_ID_IDLE;
        wake_param = dev; //< OSPORT-PIN 唤醒
        __OSAL_LOG("[osal.c] osport wake:%ld\r\n", dev);
        return SUCCESS;
    }

    for (pWake++; pWake < (&__ComPonent_Wakeup_OSAL_WakeupHandlerEnd0); pWake++)
    {
        if (pWake->irq_dev == dev)
        {
            param = pWake->cb(pWake->irq_dev);
            if (param > 0)
            {
                wake_id = pWake->comp_id;
                wake_param = (uint32_t)param;
                __OSAL_LOG("[osal.c] OSAL_WakeupHandler, wake_id:%ld  wake_param:%ld\r\n", wake_id, wake_param);
                return SUCCESS;
            }
        }
    }

#if defined(SLEEP_CHECK_OCEP_STATUS)
extern uint32_t Lock_WakeupCheckSenser(void);
    if (wakeTimes >= 10)
    {
        wakeTimes = 0;
        if (Lock_WakeupCheckSenser())
        {
            wake_id = COMP_LOCK;
            wake_param = vPIN_B20;
            __OSAL_LOG("[osal.c] wake_id:%ld  wake_param:%ld\r\n", wake_id, wake_param);
            return SUCCESS;
        }
    }
#endif

#if defined(SLEEP_CHECK_AUTO_LOCK)

    if (wakeUpCheckRemainTime())
    {
        wake_id = COMP_LOCK;
        wake_param = 5;
        __OSAL_LOG("[osal.c] wake_id:%ld  wake_param:%ld\r\n", wake_id, wake_param);
        return SUCCESS;
    }
#endif

    if ((param == -1) && ((dev >> 8) != vTIMER) && osalStatus == OSAL_STA_SLEEP)
    {
        for (int i=0; i<15; i++)//< 查pSleepEvent，等待15ms
        {
            for (uint16_t index = 0; index < g_TaskQty; index++)
            {
                if (pSleepEventsList[index] & EVENT_SYS_ISR)
                {
                    wake_id = OSAL_TaskIndex2CompId(index);
                    wake_param = dev;
                    __OSAL_LOG("[osal.c] pSleepEventsList non empty, wake_id:%ld  wake_param:%ld\r\n", wake_id, wake_param);
                    return SUCCESS;
                }
            }
            Device_DelayMs(1);
        }
    }
    return ERROR;
}

extern void Gpio_SetB2BWakeup(void);
/**
  * @brief  OSAL深度睡眠
  * @details 详细说明:系统进入深度睡眠状态
  *         
  *         
  * @return NULL
  */
static void OSAL_DeepSleep(void)
{
    uint32_t device = (vPIN << 8) | 0xFF;

    uint32_t timestamp  = OSAL_GetTick();      //< 进入休眠的时刻
    uint32_t sleep_time = OSAL_TimerGetMin();  //< 需要的睡眠时间
    uint32_t past_time  = 0;
    __OSAL_LOG("[osal.c] OSAL_DeepSleep:%ld\r\n", sleep_time);
    for (;;)
    {
        /* 处理唤醒回调 */
        if (device != vNOHARDWARE)
        {
            if (OSAL_WakeupHandler(device) != ERROR)
            {
                // 检测到唤醒事件，B2B互相唤醒
                // TODO: osport 发送软定时器处理延时    
                Gpio_SetB2BWakeup();
                if (device != vPIN_I1 && device != vPIN_I22)
                {
                    #if defined(SLAVE_DEVICE)
                    // 若非B2B唤醒 延时30ms，等待B2B唤醒完成  B2B唤醒去抖操作需要持续4ms电平保持
                    // 主机要处理电量  触摸初始化  用户列表初始化 多耗费 8 + 10 + 7 ms
                    // HK01主机36ms后初始化完成进入APP调度
                    co_delay_ms(35); 
                    #else
                    // 若非B2B唤醒 延时10ms，等待B2B唤醒完成  B2B唤醒去抖操作需要持续4ms电平保持
                    // 从机10ms后初始化完成进入APP调度
                    co_delay_ms(15); 
                    #endif
                }

                return;
            }
        }
        /* 计算剩余睡眠，让CPU进入DEEP SLEEP */
        uint32_t remaining_time = sleep_time - past_time;
        // __OSAL_LOG("[osal.c] wake remaining_time:%ld, sleep_time:%d\r\n", remaining_time, sleep_time);
        device = Device_DeepSleep((remaining_time >= wakeup_interval) ? wakeup_interval : remaining_time);
        if(device != vNOHARDWARE)
        {
            __OSAL_LOG("[osal.c] wake device:%ld, 0x%x\r\n", device, device);
        }
        /* 计算当前实际睡眠的时间 */
        uint32_t xConstTickCount = OSAL_GetTick();
        past_time = OSAL_PastTime(xConstTickCount, timestamp);
        // __OSAL_LOG("[osal.c] wake past_time:%ld, sleep_time:%d\r\n", past_time, sleep_time);
        /* 需要的睡眠时间到了：直接唤醒 */
        if (past_time >= sleep_time)
        {
            __OSAL_LOG("[osal.c] wake device:%ld\r\n", device);
            wake_id = TASK_ID_IDLE;
            wake_param = 1;  //< TIMER 唤醒
            return;
        }
    }
}

/**
  * @brief  睡眠前的检查（从机端）
  * @details 不需要做任何检查
  *         
  * @param[in]  delay:当前设定的自动休眠的值ms
  * 
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误）
  */
__attribute__((weak)) ErrorStatus OSAL_SleepCheck(uint32_t *delay)
{
    return OSAL_TaskStatusCheckLocal();
}

/**
  * @brief  OSAL处理自动休眠逻辑（这个函数是一个定时器处理函数）
  * @details 详细说明:pTimer->events：定时器参数，由创建时给定的值
  *                  这里为真表示需要执行休眠回调，为假表示不执行休眠回调     
  *    
  * @param[in]  handle：定时器句柄
  *      
  * @return NULL
  */
static void OSAL_AutoSleepTimer(TimerHandle_stu_t handle)
{
    if (g_SystemResetFlag == SET)
    {
        Device_CpuReset(0);
        while(1);
    }

    TimerType_stu_t *pTimer = (TimerType_stu_t *)handle;
    if (pTimer->events != 0)
    {
        if (OSAL_SleepCheck(&pTimer->delay) != SUCCESS)
        {
            return;
        }
    }
    
    if (OSAL_Sleep() != ERROR)
    {
        OSAL_TimerDelete(handle);
        auto_sleep_timer_handle = NULL;
    }
    else
    {
        pTimer->delay = 1000;
    }
}
#endif

/**
  * @brief  系统空闲任务
  * @details 详细说明：1、处理启动与休眠
  *                   2、管理软定时器链表
  *                   3、管理消息服务     
  *      
  * @return NULL
  */
static void OSAL_IdleTask(void)
{
	static uint32_t backupTicks = 0;
	const  uint32_t xConstTickCount = OSAL_GetTick();

	if (backupTicks == xConstTickCount)
	{
        return;
    }
	backupTicks = xConstTickCount;

    if (osalStatus == OSAL_STA_START_APP)
    {
        g_ActiveAppIndex = APP_NO_APP - 1;
        OSAL_OsportConfig(ENABLE);
        g_ActiveAppIndex = APP_NO_APP;

        osalStatus = OSAL_STA_ACTIVE;
        OSAL_CopySleepEvent();
        OSAL_AppStart(wake_id, wake_param);
        __OSAL_LOG("[osal.c] System boot complete\r\n\r\n");
    }
    else if (osalStatus == OSAL_STA_SLEEP)
    {
    #if KOS_PARAM_SLEEP_FUNC
        if (OSAL_OsportConfig(DISABLE) == SUCCESS)
        {
            Device_Disable(vCPU_0);
            OSAL_DeepSleep();
            Device_Enable(vCPU_0);
        }
        else
        {
            wake_id = TASK_ID_IDLE;
            wake_param = 3;  //< OSPROT 休眠失败，然后又直接跑唤醒流程
            __OSAL_LOG("[osal.c] Osport sleep failed\r\n");
        }
    #endif
        osalStatus = OSAL_STA_START_TASK;
    }
    else if (osalStatus == OSAL_STA_START_TASK)
    {
    #if defined(KOS_PARAM_ROLE_SLAVE)
        OSAL_QueueReset(publish_queue);
    #endif
        __OSAL_LOG("[osal.c] OSAL_StartHook...\r\n");
        OSAL_StartHook();



        __OSAL_LOG("[osal.c] OSAL_Start\r\n");
        OSAL_Start();
        osalStatus = OSAL_STA_START_APP;
    }
    else if (osalStatus == OSAL_STA_ACTIVE)
    {
        OSAL_OsPortProcess();
        OSAL_MessageBroker();
        OSAL_TimerListUpdate(); //OSAL_Sleep();
    }
    Device_FeedDog();
}

/**
  * @brief  系统运行
  * @details 详细说明：无     
  *      
  * @return NULL
  */
void OSAL_Running(void)
{
	uint32_t events;
	uint16_t index;
    
	for (;;)
	{
        OSAL_LoopHook();

		for (index = 0; index < eventListMaxRange; index++)
		{
			if (pEventsList[index])
			{
				break;
			}
		}

		if (index < eventListMaxRange)
		{
			Device_EnterCritical();
			events = pEventsList[index];
			pEventsList[index] = 0;
			Device_ExitCritical();
			
			g_ActiveTaskIndex = index % g_TaskQty;
            events = (pTasksList[g_ActiveTaskIndex].pTaskFun == NULL) ? 0 : pTasksList[g_ActiveTaskIndex].pTaskFun(events);
			g_ActiveTaskIndex = TASK_NO_TASK;
			
			Device_EnterCritical();
			pEventsList[index] |= events;
			Device_ExitCritical();
		}
		else
		{
			g_ActiveTaskIndex = TASK_ID_IDLE;
            OSAL_IdleTask();
			g_ActiveTaskIndex = TASK_NO_TASK;
		}
	}
}

/**
  * @brief  OSAL 初始化
  * @details 详细说明：初始化系统用到的一些数据表    
  *      
  * @return NULL
  */
void OSAL_Init(void)
{
    __OSAL_LOG("[osal.c] OSAL_Init\r\n");
    OSAL_TaskListInit();
    OSAL_TimerListInit();	
    OSAL_ApplicationInit();
    OSAL_OsPortInit();
    osalStatus = OSAL_STA_START_TASK;

#if defined(KOS_PARAM_ROLE_SLAVE)
    /**
     * 用来缓存待publish的消息
     * 当主从还未建立连接又需要publish时就会先暂存到这个队列
     */
    publish_queue = OSAL_QueueCreate(30);
    OSAL_ASSERT(publish_queue != NULL);
#endif
}

/**
  * @brief  设置任务状态
  * @details 详细说明:只能在组件层（TASK里面）调用
  *         
  * @param[in]  status：状态
  *         
  * @return NULL
  */
void OSAL_SetTaskStatus(TaskStatus_enum_t status)
{
    OSAL_ASSERT(g_ActiveTaskIndex < g_TaskQty);

    if (pTasksList[g_ActiveTaskIndex].status != status)
    {
        pTasksList[g_ActiveTaskIndex].status = status;
        OSAL_SendSync(g_ActiveTaskIndex, 0, 0);
    }
}

#if KOS_PARAM_SLEEP_FUNC
/**
  * @brief  刷新休眠时间
  * @details 详细说明:无
  *         
  * @param[in]  time：时间值（ms）
  * @param[in]  param：1:休眠前执行回调，0:休眠前不执行回调
  *         
  * @return NULL
  */
void OSAL_RefreshSleepTime(uint32_t time, uint32_t param)
{
    if (g_SystemResetFlag != SET)
    {
        auto_sleep_timer_handle = OSAL_TimerAdd(APP_NO_APP, param, OSAL_AutoSleepTimer, time, SET);
    }
}

/**
  * @brief  更新休眠时间 （从机端）
  * @details 详细说明:无
  *         
  * @param[in]  time：时间值（ms）
  * @param[in]  param：1:休眠前执行回调，0:休眠前不执行回调
  *         
  * @return NULL
  */
__attribute__((weak)) void OSAL_UpdateSleepTime(uint32_t time, uint32_t param)
{
    OSAL_RefreshSleepTime(time, param);
}

/**
  * @brief  获取自动休眠TIMER的剩余定时时间
  * @details 详细说明:无
  *
  *         
  * @return NULL
  */
uint32_t OSAL_GetAutoSleepTime(void)
{
    const uint32_t xConstTickCount = OSAL_GetTick();
    TimerType_stu_t *pTimer = auto_sleep_timer_handle;
    uint32_t past_time;

    if (pTimer == NULL)
    {
        return UINT32_MAX;
    }
    past_time = OSAL_PastTime(xConstTickCount, pTimer->timestamp);
    return (past_time < pTimer->delay) ? (pTimer->delay - past_time) : 0;
}
#endif

/**
  * @brief  系统复位
  * @details 详细说明:无
  *         
  * @param[in]  time：0表示立即复位，其它表示延时复位
  *         
  * @return NULL
  */
void OSAL_SystemReset(uint32_t time)
{
    if (time == 0)
    {
        Device_CpuReset(0);
    }
#if KOS_PARAM_SLEEP_FUNC
    else
    {
        OSAL_UpdateSleepTime(time, 0);
        g_SystemResetFlag = SET;
    }
#endif
}

/**
  * @brief  阻塞延时
  * @details 详细说明:无
  *         
  * @param[in]  time：时间值（单位US）
  *         
  * @return NULL
  */
void OSAL_DelayUs(uint32_t time)
{
    Device_DelayUs(time);
}

/**
  * @brief  杀狗
  * @details 详细说明:执行该函数外部看门狗会复位系统
  *         
  *         
  * @return NULL
  */
void OSAL_KillDog(void)
{
    Device_KillDog();
}

/**
  * @brief  OSAL系统滴答中断服务函数
  * @details 详细说明:虚拟设备vTIMER_0作为系统滴答定时器
  *         
  *         
  * @return NULL
  */
void OSAL_SysTickHandler(void)
{
	xTickCount = xTickCount + 1;
}

/**
  * @brief  加解密接口
  * @details 详细说明:无
  *         
  * @param[in]  param：加解密参数，具体参考Crypto_enum_t枚举
  * @param[in]  src：源
  * @param[in]  len：源的字节数
  * @param[in]  dst：目的地
  * @param[in]  key：密钥
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_Crypto(Crypto_enum_t param, void *src, uint32_t len, void *dst, void *key)
{
    return (Device_Crypto(param, src, len, dst, key) < 0) ? ERROR : SUCCESS;
}

/**
  * @brief  写NV数据
  * @details 详细说明:Nv读写接口，在不同的组件里调用，操作的是不同的NV区域
  *                   APP层有一个NV区域、每个组件创建时也会分配一块NV区域
  *         
  * @param[in]  addr：地址
  * @param[in]  in_data：数据指针
  * @param[in]  len：数据长度
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_NvWrite(uint32_t addr, void *in_data, uint32_t len)
{
    uint32_t nv_addr = 0, nv_size = 0;

    if (g_ActiveAppIndex != APP_NO_APP)
    {
        /* 应用层调用 */
        nv_addr = app_nv_addr;
        nv_size = app_nv_size;
    }
    else if (g_ActiveTaskIndex < g_TaskQty)
    {
        /* 组件层调用 */
        nv_addr = pTasksList[g_ActiveTaskIndex].nv_addr;
        nv_size = pTasksList[g_ActiveTaskIndex].nv_size;
    }
    else
    {
        return ERROR;
    }

    if ((nv_size > 0) && (addr + len <= nv_size))
    {
        if (Device_Write(vEEPROM_0, in_data, len, nv_addr + addr) >= 0)
        {
            if (osalStatus == OSAL_STA_ACTIVE)
            {
                OSAL_SendSync(g_ActiveTaskIndex, 0, 0);
            }
            return SUCCESS;
        }
    }
    return ERROR;
}

/**
  * @brief  读NV数据
  * @details 详细说明:Nv读写接口，在不同的组件里调用，操作的是不同的NV区域
  *                   APP层有一个NV区域、每个组件创建时也会分配一块NV区域
  *         
  * @param[in]  addr：地址
  * @param[in]  in_data：数据指针
  * @param[in]  len：数据长度
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_NvRead(uint32_t addr, void *out_data, uint32_t len)
{
    uint32_t nv_addr = 0, nv_size = 0;

    if (g_ActiveAppIndex != APP_NO_APP)
    {
        /* 应用层调用 */
        nv_addr = app_nv_addr;
        nv_size = app_nv_size;
    }
    else if (g_ActiveTaskIndex < g_TaskQty)
    {
        /* 组件层调用 */
        nv_addr = pTasksList[g_ActiveTaskIndex].nv_addr;
        nv_size = pTasksList[g_ActiveTaskIndex].nv_size;
    }
    else
    {
        return ERROR;
    }

    if ((nv_size > 0) && (addr + len <= nv_size))
    {
        return Device_Read(vEEPROM_0, out_data, len, nv_addr + addr) < 0 ? ERROR : SUCCESS;
    }
    else
    {
        return ERROR;
    }
}

/**
  * @brief  获取指定组件的NV-INFO
  * @details 详细说明:无
  *         
  * @param[in]  comp_id：组件ID
  * @param[in]  addr：组件NV-INFO
  * @param[in]  size：组件NV-INFO
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_NvGetInfo(uint16_t comp_id, uint8_t alias, uint32_t *addr, uint32_t *size)
{
    uint8_t index = OSAL_CompId2TaskIndex(comp_id);

    if (index != 0xFF)
    {
        if (pTasksList[index].alias == 0 || pTasksList[index].alias == alias)
        {
            *addr = pTasksList[index].nv_addr;
            *size = pTasksList[index].nv_size;
            return SUCCESS;
        }
    }
    return ERROR;
}

/**
  * @brief  发送一个消息到本地组件的邮箱
  * @details 详细说明:无
  *         
  * @param[in]  comp_id：组件ID
  * @param[in]  alias：组件昵称
  * @param[in]  msg：数据指针
  * @param[in]  size：数据长度
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_MboxPostLocal(uint16_t comp_id, uint8_t alias, void *msg, uint16_t size)
{
    uint16_t index = OSAL_CompId2TaskIndex(comp_id);

    if (index < g_TaskQty)
    {
        if (alias == pTasksList[index].alias || 0 == pTasksList[index].alias)
        {
            OSAL_EventSet(index + ((int)EVT_PRIORITY_MEDIUM * g_TaskQty), EVENT_SYS_MBOX);
            if (OSAL_QueueSendToBack(pTasksList[index].queue, msg, size) == SUCCESS)
            {
                return SUCCESS;
            }
        }
    }
    return ERROR;
}

/**
  * @brief  从当前组件的邮箱中得到一个消息
  * @details 详细说明:无
  *         
  * @param[in]  msg：数据指针
  *         
  * @return 返回数据长度
  */
uint16_t OSAL_MboxAccept(void *msg)
{
    OSAL_ASSERT(g_ActiveTaskIndex < g_TaskQty);
    return OSAL_QueueReceive(pTasksList[g_ActiveTaskIndex].queue, msg);
}

/**
  * @brief  从当前组件的邮箱中得到消息数量和最前面一个消息的size
  * @details 详细说明:无
  *         
  * @param[in]  size：返回队列里面最前面那个数据的SIZE
  *         
  * @return 返回消息数量
  */
uint16_t OSAL_MboxLenght(uint16_t *size)
{
    OSAL_ASSERT(g_ActiveTaskIndex < g_TaskQty);
    return OSAL_QueueLenght(pTasksList[g_ActiveTaskIndex].queue, size);
}

/**
  * @brief  给当前组件设置昵称
  * @details 详细说明:无
  *         
  * @param[in]  alias：昵称名
  *         
  * @return NULL
  */
void OSAL_SetCompAlias(uint8_t alias)
{
    OSAL_ASSERT(g_ActiveTaskIndex < g_TaskQty);
    pTasksList[g_ActiveTaskIndex].alias = alias;
}

/**
  * @brief  发布消息（从机端）（通过os2os将消息发到主OS）
  * @details 详细说明:只能在TASK里面调用
  *         
  * @param[in]  pMsg：消息实体的地址
  * @param[in]  len：消息长度
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
__attribute__((weak)) ErrorStatus OSAL_MessagePublish(void *msg, uint16_t len)
{
    OSAL_ASSERT((msg != NULL) && (len != 0) && (g_ActiveTaskIndex < g_TaskQty));

    if (g_SystemResetFlag == RESET)
    {
        uint16_t comp_id = pTasksList[g_ActiveTaskIndex].comp_id;
        uint16_t alias   = pTasksList[g_ActiveTaskIndex].alias;

        if (len & 0x8000)
        {
            len &= ~0x8000;
            comp_id = 0xF0;//COMP_SYS_MSG;
        }
        
        __OSAL_LOG("[osal.c] Publish, comp_id:%d, alias:%d\r\n", comp_id, alias);
        publish_flag = SET;

    #if !defined(KOS_PARAM_ROLE_SLAVE)
        OSAL_OsPortSend((VirtualHardware_enum_t)0, OSPORT_CMD_PUBLISH, comp_id, alias, msg, len);
    #else
        if(comp_id != COMP_EXTEND_KDS)
        {
            if (OSAL_OsPortSend((VirtualHardware_enum_t)0, OSPORT_CMD_PUBLISH, comp_id, alias, msg, len) != SUCCESS)
            {
                uint8_t *temp = OSAL_Malloc(len+2);
                OSAL_ASSERT(temp != NULL);
                temp[0] = comp_id;
                temp[1] = alias;
                memcpy(temp+2, msg, len);
                OSAL_QueueSendToBack(publish_queue, temp, len+2);
                OSAL_Free(temp);
                __OSAL_LOG("[osal.c] Publish failed, save to publish_queue\r\n");
            }
        }
        OSAL_MessageAdd(comp_id, msg, len);
    #endif
        return SUCCESS;
    }
    return ERROR;
}

#if defined(KOS_PARAM_ROLE_SLAVE)
/**
  * @brief  发出队列里面积压的数据
  *         
  * @note   握手成功后执行
  */
static void OSAL_MessagePublishFromQueue(void)
{
    uint16_t size = 0;
    while (OSAL_QueueLenght(publish_queue, &size) > 0)
    {
        uint8_t *buffer = (uint8_t *)OSAL_Malloc(size);
        OSAL_ASSERT(buffer != NULL);
        OSAL_QueueReceive(publish_queue, buffer);
        uint16_t comp_id = buffer[0];
        uint16_t alias   = buffer[1];
        __OSAL_LOG("[osal.c] Publish from publish_queue, comp_id:%d, alias:%d\r\n", comp_id, alias);
        OSAL_OsPortSend((VirtualHardware_enum_t)0, OSPORT_CMD_PUBLISH, comp_id, alias, buffer+2, size-2);
        OSAL_Free(buffer);
    }

#if KOS_PARAM_SLEEP_FUNC
    if (auto_sleep_timer_handle != NULL)
    {
        TimerType_stu_t *pTimer = (TimerType_stu_t *)auto_sleep_timer_handle;
        pTimer->timestamp = OSAL_GetTick();
    }
#endif
}

/**
  * @brief  检查PUBLISH队列
  *         
  * @return 返回队列里面缓存的待发出的数据长度
  */
uint16_t OSAL_CheckPublishQueue(void)
{
    return OSAL_QueueLenght(publish_queue, NULL);
}
#endif

/**
  * @brief  处理OSPROT收到的命令 -- 从机端
  * @details 详细说明:无
  *         
  * @param[in]  port：端口
  * @param[in]  cmd：命令字
  * @param[in]  data：数据
  * @param[in]  len：数据长度
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误）
  */
__attribute__((weak)) void OSAL_ProcessOsportCmd(VirtualHardware_enum_t port, uint8_t cmd, uint8_t *data, uint16_t len)
{
    if (cmd == OSPORT_CMD_HELLO)
    {
        if ((data[0] == 0xFF && data[1] == 0) ||  //< 收到主机HELLO命令（FF 00）：表示主机上电启动
            (data[0] == 0xFF && data[1] == 0xFF)) //< 收到主机HELLO命令（FF FF）：表示主机转发HELLO命令（从机上电发HELLO给主机、主机会回发给从机HELLO）
        {
            if (publish_flag == SET && data[0] == 0xFF && data[1] == 0)
            {
                /* 从机发过Publish命令，并且当前收到了主机上电握手：此时从机自己执行一次重启 */
                __OSAL_LOG("[osal.c] Hello reset\r\n");
                Device_CpuReset(0);
                while (1);
            }

            if (sync_flag == RESET || (data[0] == 0xFF && data[1] == 0))
            {
                uint32_t rm = 0, rs = 0;

                /* 创建随机数Rs */
            #ifdef KOS_PARAM_OSPORT_CRYPTO
                memcpy(&rm, &data[2], len - 2);
                rs = OSAL_OsportCreateRs(port, rm);
                __OSAL_LOG("[osal.c] Rm:%08lX Rs:%08lX\r\n", rm, rs);
            #endif

                /* 用SYNC命令将TASK-INFO、Rm、Rs发给主机 */
                OSAL_SendSync(0xFF, rm, rs);
                sync_flag = SET;

                /* 把队列里面缓存的消息全部publish出去 */
            #if defined(KOS_PARAM_ROLE_SLAVE)
                OSAL_MessagePublishFromQueue();
            #endif
            }
        }
    }
    else if (cmd == OSPORT_CMD_MBOX)
    {
        uint8_t comp_id = data[0];
        uint8_t alias = data[1];
        OSAL_MboxPostLocal(comp_id, alias, data + 2, len - 2);
    }
#if KOS_PARAM_SLEEP_FUNC
    else if (cmd == OSPORT_CMD_UPDATE_SLEEP)
    {
        uint32_t time;
        memcpy(&time, data + 2, 4);
        __OSAL_LOG("[osal.c] Synch sleep time: %ld\r\n", time);
        if (time != UINT32_MAX)
        {
            time += 150;
        }
        OSAL_UpdateSleepTime(time, data[0]);
    }
#endif
}

/**
  * @brief 设置睡眠下间隔唤醒的时间
  * @details 详细说明:无
  *         
  * @param[in]  time：唤醒间隔时间
  *         
  */
void OSAL_SetWakeupInterval(uint32_t time)
{
    wakeup_interval = time;
}